﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage.Streams;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Net.Http.Headers;

namespace System.Net.Shared
{
    static class HttpRequestHelper
    {
        static internal HttpStatusCode _lastResultCode { get; private set; }
        static internal string _lastErrorReason { get; private set; }
        static internal bool LargeResultReturning = false;
        static internal bool SendingLargeRequest = false;
        public static async Task<string> simpleHttpPost(string url, string postData = "", string authHeader = "")
        {
            HttpContent headers = null;

            _lastResultCode = HttpStatusCode.Unused;
            _lastErrorReason = "";
            var uri = new Uri(url);
            using (var handler = new HttpClientHandler())
            {
                if (SendingLargeRequest)
                    handler.MaxRequestContentBufferSize = Int32.MaxValue;
                SendingLargeRequest = false; 
                using (var client = new HttpClient(handler))
                {
                    if (LargeResultReturning)
                        client.MaxResponseContentBufferSize = Int32.MaxValue;
                    LargeResultReturning = false;
                    var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url);

                    if (!String.IsNullOrEmpty(authHeader))
                    {
                        httpRequestMessage.Headers.Add(System.Net.HttpRequestHeader.Authorization.ToString(),
                                                System.Convert.ToBase64String(System.Text.UTF8Encoding.UTF8.GetBytes(
                                                    authHeader)));
                    }

                    if (String.IsNullOrEmpty(postData))
                    {
                        httpRequestMessage.Content = new StringContent(postData);
                    }

                    HttpResponseMessage result;
                    result = await client.SendAsync(httpRequestMessage);

                    _lastResultCode = result.StatusCode;

                    if (result.IsSuccessStatusCode)
                        return await result.Content.ReadAsStringAsync();

                    _lastErrorReason = result.ReasonPhrase;
                    return "";
                }
            }
            return "";
        }
        public static async Task<string> simpleHttpGet(string url, string authHeader = "")
        {
            _lastResultCode = HttpStatusCode.Unused;
            _lastErrorReason = "";

            var uri = new Uri(url);
            using (var handler = new HttpClientHandler())
            {
                if (SendingLargeRequest)
                    handler.MaxRequestContentBufferSize = Int32.MaxValue;
                SendingLargeRequest = false;
                using (var client = new HttpClient(handler))
                {
                    if (LargeResultReturning)
                        client.MaxResponseContentBufferSize = Int32.MaxValue;
                    LargeResultReturning = false;

                    var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);

                    if (!String.IsNullOrEmpty(authHeader))
                    {
                        httpRequestMessage.Headers.Add(System.Net.HttpRequestHeader.Authorization.ToString(),
                                                authHeader);
                    }

                    HttpResponseMessage result;
                    result = await client.SendAsync(httpRequestMessage);

                    _lastResultCode = result.StatusCode;

                    if (result.IsSuccessStatusCode)
                        return await result.Content.ReadAsStringAsync();

                    _lastErrorReason = result.ReasonPhrase;
                    return "";
                }
            }
        }
        public static async Task<string> simpleHttpPut(string url, byte[] fileContents, string authHeader = "")
        {
            _lastResultCode = HttpStatusCode.Unused;
            _lastErrorReason = "";

            var uri = new Uri(url);
            using (var handler = new HttpClientHandler())
            {
                if (SendingLargeRequest)
                    handler.MaxRequestContentBufferSize = Int32.MaxValue;
                SendingLargeRequest = false;
                using (var client = new HttpClient(handler))
                {
                    if (LargeResultReturning)
                        client.MaxResponseContentBufferSize = Int32.MaxValue;
                    LargeResultReturning = false;
                    
                    var httpRequestMessage = new HttpRequestMessage(HttpMethod.Put, url);

                    if (!String.IsNullOrEmpty(authHeader))
                    {
                        httpRequestMessage.Headers.Add(System.Net.HttpRequestHeader.Authorization.ToString(),
                                                authHeader);
                    }

                    HttpResponseMessage result;
                    httpRequestMessage.Content = new ByteArrayContent(fileContents);
                    result = await client.SendAsync(httpRequestMessage);

                    _lastResultCode = result.StatusCode;
                    if (result.IsSuccessStatusCode)
                        return await result.Content.ReadAsStringAsync();

                    _lastErrorReason = result.ReasonPhrase;
                    return "";
                }
            }
        }
        public static async Task<string> simpleHttpPut(string url, Stream fileStream, string authHeader = "")
        {
            _lastResultCode = HttpStatusCode.Unused;
            _lastErrorReason = "";

            var uri = new Uri(url);
            using (var handler = new HttpClientHandler())
            {
                if (SendingLargeRequest)
                    handler.MaxRequestContentBufferSize = Int32.MaxValue;
                SendingLargeRequest = false;

                using (var client = new HttpClient(handler))
                {
                    if (LargeResultReturning)
                        client.MaxResponseContentBufferSize = Int32.MaxValue;
                    LargeResultReturning = false;

                    var httpRequestMessage = new HttpRequestMessage(HttpMethod.Put, url);

                    if (!String.IsNullOrEmpty(authHeader))
                    {
                        httpRequestMessage.Headers.Add(System.Net.HttpRequestHeader.Authorization.ToString(),
                                                authHeader);
                    }

                    HttpResponseMessage result;
                    //var strmContents = new StreamContent(fileStream);
                    httpRequestMessage.Content = new StreamContent(fileStream);
                    result = await client.SendAsync(httpRequestMessage); 

                    _lastResultCode = result.StatusCode;
                    if (result.IsSuccessStatusCode)
                        return await result.Content.ReadAsStringAsync();

                    _lastErrorReason = result.ReasonPhrase;
                    return "";
                }
            }
        }
        public static async Task<byte[]> simpleHttpGetBuffer(string url, string authHeader = "")
        {
            _lastResultCode = HttpStatusCode.Unused;
            _lastErrorReason = "";

            var uri = new Uri(url);
            using (var handler = new HttpClientHandler())
            {
                if (SendingLargeRequest)
                    handler.MaxRequestContentBufferSize = Int32.MaxValue;
                SendingLargeRequest = false;

                using (var client = new HttpClient(handler) { MaxResponseContentBufferSize = Int32.MaxValue })
                {
                    var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);

                    if (!String.IsNullOrEmpty(authHeader))
                    {
                        httpRequestMessage.Headers.Add(System.Net.HttpRequestHeader.Authorization.ToString(),
                                                authHeader);
                    }
                    
                    HttpResponseMessage result;
                    result = await client.SendAsync(httpRequestMessage);
                    _lastResultCode = result.StatusCode;

                    if (result.IsSuccessStatusCode)
                    {
                        var buffer = await result.Content.ReadAsByteArrayAsync();
                        return buffer;
                    }

                    _lastErrorReason = result.ReasonPhrase;
                    return null;
                }
            }
        }

        internal async static Task<bool> simpleHttpGetSavedToStream(string url, Func<Stream> getStreamFunc, string authHeader = "")
        {
            _lastResultCode = HttpStatusCode.Unused;
            _lastErrorReason = "";

            var uri = new Uri(url);

            using (var handler = new HttpClientHandler())
            {
                if (SendingLargeRequest)
                    handler.MaxRequestContentBufferSize = Int32.MaxValue;
                SendingLargeRequest = false;

                using (var client = new HttpClient(handler) { MaxResponseContentBufferSize = Int32.MaxValue })
                {
                    var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);

                    if (!String.IsNullOrEmpty(authHeader))
                    {
                        httpRequestMessage.Headers.Add(System.Net.HttpRequestHeader.Authorization.ToString(),
                                                authHeader);
                    }

                    HttpResponseMessage result;
                    result = await client.SendAsync(httpRequestMessage);
                    _lastResultCode = result.StatusCode;

                    if (result.IsSuccessStatusCode)
                    {
                        try
                        {
                            if (getStreamFunc != null)
                                using (var strmOut = getStreamFunc())
                                    await result.Content.CopyToAsync(strmOut);
                        }
                        catch (Exception ex)
                        {
                            _lastResultCode = HttpStatusCode.NotAcceptable;
                            _lastErrorReason = ex.Message;
                            return false;
                        }
                        return true;
                    }

                    _lastErrorReason = result.ReasonPhrase;
                    return false;
                }
            }
        }
    }
}
